<?php 
namespace app\authorization\model;
use think\Model;
use think\Db;
use app\admin\model\AccessModel;
use app\common\lib\AccessAuthorization;

/**
 * 
 */
class RbacMenuModel extends Model
{


	/**
	 * 获取所有角色信息表
	 */
	public function getAllRoleInfo( $id = 0 , $str = '' )
	{
		$list = [];
		$find = Db::name( 'role' )->where( 'parent_id' , $id  )->select();
		foreach ( $find as $key => $value ) {
			$tmp [ 'id' ] = $value [ 'id' ] ;
			$tmp [ 'title' ] = $value [ 'name' ] . $str( $value [ 'id' ] , $this->getUserByRoleId( $value['id'] , 'get_user_count' ) ) ;
			$tmp [ 'children' ] = $this->getAllRoleInfo( $value [ 'id' ] , $str );
			$list [] = $tmp;
		}
		return $list;
	}

	/**
	 * 获取所有parent为0的菜单,以及下面的子菜单
	 */
	public function getBaseMenu( $versionId , $parent = 0)
	{
		$list = [];
		$baseMenu = Db( 'admin_menu' )->where( 'parent_id' , $parent )->where( 'app' , 'NOT LIKE' , 'plugin%'  )->order('list_order')->select();
		foreach ($baseMenu as $key => $value) {
			$tmp [ 'id' ] = $value [ 'id' ] ;
			$tmp [ 'title' ] = $value [ 'name' ];
			$isCheck = Db( 'access_versions_menu' )->where( 'access_versions_id' , $versionId )->where('menu_id' , $value[ 'id' ] )->find();
			$tmp [ 'checked' ] = $isCheck ? true :  false ;
			$tmp [ 'children' ] = $this->getBaseMenu( $versionId , $value [ 'id' ] );
			$list [] = $tmp;
		}
		return $list;
	}

	/**
	 * 更新版本菜单
	 *updateList 中保存的是原始菜单id
	 */
	public function updateVersions( $versionId , $updateList )
	{
		//获取需要删除的数据
		$deleteList = Db( 'access_versions_menu' )->where( 'access_versions_id' , $versionId )->where( 'menu_id' , 'NOT IN' , $updateList )->column( 'id' );

		//获取已存在表中的数据
		$hasList = Db( 'access_versions_menu' )->where( 'access_versions_id' , $versionId )->where( 'menu_id' , 'IN' , $updateList )->column( 'menu_id' );


		//获取需要新增的数据  
		$insertList = array_diff( $updateList , $hasList );

		$insert = [];
		foreach ($insertList as $key => $id ) {
			$menu = Db('admin_menu')->where( 'id' , $id )->find();
			$tmp [ 'access_versions_id' ] = $versionId;
			$tmp [ 'rule_name' ] = $menu['app'].'/'.$menu['controller'].'/'.$menu['action'];
			$tmp [ 'type' ] = $menu[ 'type' ];
			$tmp [ 'create_time' ] = time();
			$tmp [ 'menu_id' ] = $id;
			$insert [] = $tmp;
		}


		try {
			//删除多余的
			if( !empty( $deleteList ) ){
				Db( 'access_versions_menu' )->where( 'id' , 'IN' , $deleteList )->delete();
			}
			//插入没有的
			if( !empty( $insert ) ){
				Db( 'access_versions_menu' )->insertAll( $insert );
			}
		} catch (\Exception $e) {
			return false;
		}
		
		return true;
	}

	////////////////////////////////////////////////////////////////
	///////////////////
	///////////////////  角色授权部分
	//////////////////
	///////////////////////////////////////////////////////////////

	/**
	 * 根据权限id获取角色菜单
	 * 1.获取角色所在公司的版本菜单信息和公司模块菜单的交集为基础
	 * 2.根据公司获取安装的模块菜单信息 ( 模块子菜单区分版本 )
	 */
	public function getMenuListByRoleId( $roleId )
	{
		$list = [];
		$company = $this->getCompanyInfoByRoleId( $roleId , ',c.versions_type as versions' );

		//获取基础菜单(版本菜单)
		$versionMenu = Db( 'access_versions_menu' )->where( 'access_versions_id' , $company[ 'versions' ] )->column( 'menu_id' );
		if( empty( $versionMenu ) ){
			return [ 'status'=>false, 'message'=>'未获取到权限菜单版本信息,请设置版本信息后再操作!' ];
		}
		
		

		//获取已经安装的模块菜单
		$moduleMenuList = Db( 'module_menu' )->where( 'company_id' , $company [ 'id' ] )->select()->toArray();

		//获取模块菜单id
		$moduleMenus = array_map( function( $value ){
			if( isset( $value [ 'menu_id' ] ) ) return $value [ 'menu_id' ];
		} , $moduleMenuList );


		//获取模块菜单对应的版本
		$moduleVersion = [];
		foreach ($moduleMenuList as $key => $value) {
			$moduleVersion [ $value [ 'menu_id' ] ] = Db('module_store')->where( 'id' , $value [ 'module_id' ]  )->value( 'version' );
		}

		$versionMenu = array_merge( $versionMenu , $moduleMenus );


		$menu = Db( 'admin_menu' )->where( 'id' , 'IN' , $versionMenu )->order('list_order')->select();

		$fn = function( $menu , $parent = 0 ) use ( &$fn , $roleId , $moduleMenus , $moduleVersion , $company ) {
			$list = [];
			foreach ( $menu as $key => $value ) {
				if( $value [ 'parent_id' ] == $parent ){
					//如果是模块菜单 
					if( in_array( $value [ 'id' ] , $moduleMenus ) ){
						$versionStr = '*'.$moduleVersion[ $value [ 'id' ] ].'*';
						$pos = strpos( $value['module_version'] , $versionStr );
						$custom = Db('module_menu')->where( 'company_id' , $company [ 'id' ] )->where( 'menu_id' , $value[ 'id' ])->value('custom');
						if( false === $pos && $custom != 1 ) continue;
					}
					$temp [ 'id' ] = $value [ 'id' ];
					$temp [ 'title' ] = $value [ 'name' ];
					$children = $fn( $menu , $value [ 'id' ] );
					$isCheck = Db('auth_access')->where( 'role_id' , $roleId )->where( 'menu_id' , $temp[ 'id' ] )->find();
					$temp [ 'checked'] =  ( $isCheck && empty( $children ) ) ? true :  false ;
					$temp [ 'children' ] = $children;
					$list [] = $temp;
				}
			}
			return $list;
		};

		$list = $fn( $menu );
		return $list;
	}

	/**
	 * 根据角色id获取公司信息
	 */
	private function getCompanyInfoByRoleId( $roleId , $field = '' )
	{
		$fieldStr = 'c.id,c.company_name,r.id as role_id'.$field;
		$company = Db::table( 'cmf_company' )->alias("C")->join( 'cmf_role R' , 'C.id=R.company_id' )->where( 'r.id' , $roleId )->field( $fieldStr )->find();
		return $company;
	}

	/**
	 * 获取角色下的用户
	 */
	public function getUserByRoleId( $roleId , $type = '' )
	{
		$user = Db::name( 'user_attach' )->where( 'role_id' , $roleId )->column( 'user_id' );
		if( !empty( $type ) ){
			return count( $user );
		}
		$list = Db::name( 'user' )->where( 'id' , 'IN' , $user )->field( 'id,user_login as name , user_status as status' )->select();
		return $list;
	}

	/**
	 * 角色权限管理 --- 角色权限保存
	 */
	public function saveRoleMenu( $roleId , $menu = [] )
	{
		$company = $this->getCompanyInfoByRoleId( $roleId , ',c.versions_type as versions' );

		//如果menu = null ,清除角色所有权限信息
		if( empty( $menu ) ){
			return Db( 'auth_access' )->where( 'company' , $company [ 'id' ] )->where( 'role_id' , $roleId )->delete();
		}
		
		//获取需要删除的数据
		$deleteList = Db( 'auth_access' )->where( 'company' , $company [ 'id' ] )->where( 'role_id' , $roleId )->where( 'menu_id' , 'NOT IN' , $menu  )->column( 'id' );

		//获取已存在的数据
		$hasList = Db( 'auth_access' )->where( 'company' , $company [ 'id' ] )->where( 'role_id' , $roleId )->where( 'menu_id' , 'IN' , $menu  )->column( 'menu_id' );

		//需要更新的数据
		$insertList = array_diff( $menu , $hasList );

		$inesrt = [];
		foreach ( $insertList as $key => $value ) {
			$find = Db('admin_menu')->where( 'id' , $value )->find();
			$ruleName = $find[ 'app' ].'/'.cmf_parse_name( $find[ 'controller' ] , 1 ).'/'.$find[ 'action' ];
			$tmp=[
				'role_id' =>  $roleId,
				'rule_name' => $ruleName ,
				'type' =>  'admin_url',
				'company' => $company [ 'id' ] ,
				'menu_id' =>  $value ,
				'access_versions_id' => $company [ 'versions' ] 
			];
			$insert [] = $tmp;
		}

		try {
			//删除多余的
			if( !empty( $deleteList ) ){
				Db( 'auth_access' )->where( 'id' , 'IN' , $deleteList )->delete();
			}
			//插入没有的
			if( !empty( $insert ) ){
				Db( 'auth_access' )->insertAll( $insert );
			}
		} catch (\Exception $e) {
			return false;
		}
		
		return true;
	}

	/**
	 * 根据用户id获取被授权的列表信息
	 */
	public function getRbacListByUserId( $userId )
	{
		$roleId = Db( 'user_attach' )->where( 'user_id' , $userId )->value( 'role_id' );

		$company = $this->getCompanyInfoByRoleId( $roleId , ',c.versions_type as versions' );
		$cid = $company [ 'id' ] ;
		
		//获取基础菜单(版本菜单)
		$versionMenu = Db( 'access_versions_menu' )->where( 'access_versions_id' , $company[ 'versions' ] )->column( 'menu_id' );

		//获取公司的模块菜单
		$moduelMenu = Db( 'module_menu' )->where( 'company_id' , $cid )->column( 'menu_id' );


		//合并版本菜单和模块菜单
		$backgrounMenu = array_merge( $versionMenu , $moduelMenu );
	
		//获取公司最高角色菜单
		$heightRole = AccessAuthorization::getHighestRoleInfo( $userId ) ;
	
		$heightRoleMenu = Db( 'auth_access' )->where( 'company' , $cid )->where( 'role_id' , $heightRole[ 'id' ] )->where( 'access_versions_id' , $company [ 'versions' ] )->column( 'menu_id' );

		//找出该公司版本菜单与最高角色的交集菜单C
		$intersect = array_intersect( $backgrounMenu , $heightRoleMenu );
	
		//取最高角色与C的差集更新授权菜单库 auth_access  将公司所有不被授权的菜单全部删除
		$heightRoleMenuDeleteList = array_diff( $heightRoleMenu , $intersect ) ;

		if( !empty( $heightRoleMenuDeleteList ) ){
			Db( 'auth_access' )->where( 'company' , $cid )->where( 'menu_id' , 'IN' , $heightRoleMenuDeleteList )->delete();
		}

		//最后再读取当前被查询角色的菜单
		$currentMenu = db( 'auth_access' )->where( 'company' , $cid )->where( 'role_id' , $roleId )->column( 'menu_id' );


		if( empty($currentMenu) ){
			return [];
		}

		$list = [];
		$adminMenu = Db( 'admin_menu' )->where( 'id' , 'IN' , $currentMenu )->select();

		//替换菜单别名
		foreach ($adminMenu as $key => $value) {
			$alias = $this->replaceMenuAlias( $cid , $value ['id'] );
			$code = Db( 'module_menu' )->where( 'company_id' , $cid )->where( 'menu_id' , $value['id'] )->value( 'code' );
			if( !empty( $alias ) ){
				$value [ 'name' ] = $alias;
			}
			$value[ 'store_code' ] = $code;
			$list [] = $value; 
		}
		
		return $list;
	}

	/**
	 * 替换菜单别名
	 */
	private function replaceMenuAlias( $cid , $meunId ){
		$alias = Db( 'menu_alias' )->where( 'company_id' , $cid )->where( 'menu_id' , $meunId )->value( 'alias' );
		return $alias;
	}


	/**
	 * 根据菜单id 获取子菜单信息
	 */
	public function getSubMenuById( $menuId = 0 )
	{
		$list = [];
		$sub = Db( 'admin_menu' )->where( 'parent_id' , $menuId )->column( 'id' );
		foreach ($sub as $key => $value) {
			array_push( $list, $value);
			$tmp = $this->getSubMenuById( $value );
			if( !empty( $tmp ) ){
				$list = array_merge( $list, $tmp );
			}
		}
		return $list;
	}


}